package com.hubei.car.controller;

import cn.hutool.core.util.StrUtil;
import com.hubei.car.annotation.PostApi;
import com.hubei.car.constant.RedisKeyCode;
import com.hubei.car.dto.req.WechatLogin;
import com.hubei.car.entity.CarThirdUser;
import com.hubei.car.entity.Result;
import com.hubei.car.handler.BaseException;
import com.hubei.car.service.CarThirdLoginService;
import com.hubei.car.swaggerParam.CarThirdUserUpdateParam;
import com.hubei.car.utils.AesCbcUtil;
import com.hubei.car.utils.UserUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 第三方登录控制类 (最主要是用户登陆 和 回调处理 这2个接口)
 *
 * @author luokangtao
 * @create 2019-09-03 10:50
 */

@Slf4j
@RestController
@Api(value = "第三方登录接口", tags = {"第三方登录接口"})
public class CarThirdLoginController {

    //第三方登录控制类 (最主要是用户登陆 和 回调处理 这2个接口)
    @Autowired
    private CarThirdLoginService carThirdLoginService;
    @Autowired
    UserUtil userUtil;
    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${app_id_wx}")
    private String AppIdWX;//申请成功之后你会得到appId和appKey
    @Value("${authorizeURL_wx}")
    private String AuthorizeURLWX;//登陆接口 授权后 会得到一个code
    @Value("${redirect_url_wx}")
    private String RedirectUrlWX;//回调地址(host+自定义的微信回调地址)
    @Value("${scope_wx}")
    private String ScopeWX;

    //用户登陆
    @RequestMapping("/sns")
    @ApiOperation(value = "用户登录", httpMethod = "POST")
    public void thirdLogin(HttpServletRequest request, HttpServletResponse response) {
        String host = request.getHeader("host");
        //微信 state = 'fhmj'; // 防止CSRF攻击的随机参数，必传，登录成功之后会回传，最好后台自己生成然后校验合法性
        String url = AuthorizeURLWX + "?appid=" + AppIdWX + "&redirect_uri=http://" + host + RedirectUrlWX + "&response_type=code&scope=" + ScopeWX + "&state=fhmj";
        try {
            //对服务器的响应进行重定向。当server作出响应后，client客户端的请求的生存周期就终止了。
            response.sendRedirect(url);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    //微信授权登陆
    @PostApi(value = "/wx/{code}", auth = false)
    @ApiOperation(value = "微信授权登录")
    public Result<CarThirdUser> wxCallback(@PathVariable("code") String code) {
        //第三方登陆信息
        CarThirdUser carThirdUser;
        //如果不为空
        if (StrUtil.isNotBlank(code)) {
            // 根据code获取token和openid
            Map<String, String> map = carThirdLoginService.getWxTokenAndOpenid(code);
            //获取 openid
            String openId = map.get("openId");
            //如果openID存在
            if (StrUtil.isNotBlank(openId)) {
                //根据access_token和openId获取第三方用户信息存放到session中(组装数据) =>用户昵称 nickname 用户头像地址 headimgurl 用户性别 sex
                carThirdUser = carThirdLoginService.getWxUserinfo(map.get("access_token"), openId);
                // 用户第三方id 代表用户唯一身份的ID
                carThirdUser.setOpenid(openId);
                //生成token
                carThirdUser = carThirdLoginService.thirdPartyLogin(carThirdUser);
            } else {
                log.info("微信登陆失败___获取openid异常___[{}]", openId);
                throw new BaseException("微信登陆失败");
            }
        } else {
            log.info("微信登陆失败___获取code异常___[{}]", code);
            throw new BaseException("微信登陆失败");
        }
        //返回自定义的jsp页面 也可以返回结果集 让前台处理
        return Result.ok(carThirdUser);
    }

    //微信小程序授权登陆
    @PostApi(value = "/wechatLogin", auth = false)
    @ApiOperation(value = "微信小程序授权登陆")
    public Result<CarThirdUser> wechatLogin(@RequestBody WechatLogin wechatLogin) {
        //第三方登陆信息
        CarThirdUser carThirdUser = new CarThirdUser();
        //如果不为空
        if (StrUtil.isNotBlank(wechatLogin.getCode())) {
            // 根据code去调用接口获取用户openid和session_key
            Map<String, String> map = carThirdLoginService.getWechatAndOpenid(wechatLogin.getCode());
            //获取openid
            String openId = map.get("openId");
            //获取 sessionKey
            String sessionKey = map.get("sessionKey");
            //如果openID存在
            if (StrUtil.isNotBlank(sessionKey)) {
                //拿到用户session_key和用户敏感数据进行解密，拿到用户信息。
                try {
                    //解密
                    String decrypts = AesCbcUtil.decrypt(wechatLogin.getEncryptedData(), sessionKey, wechatLogin.getIv(), "utf-8");
                    log.info("解密获取用户信息:[{}]", decrypts);
                    if (StrUtil.isNotBlank(decrypts)) {
                        //根据access_token和openId获取第三方用户信息存放到session中(组装数据) =>用户昵称 nickname 用户头像地址 headimgurl 用户性别 sex
                        carThirdUser.setOpenid(openId);
                        carThirdUser = carThirdLoginService.getWechatUserinfo(decrypts, carThirdUser);
                    } else {
                        throw new BaseException("获取用户信息失败");
                    }
                } catch (Exception e) {
                    throw new BaseException("获取用户信息失败");
                }
            } else {
                log.info("微信登陆失败___获取sessionKey异常___[{}]", sessionKey);
                throw new BaseException("微信登陆失败");
            }
        } else {
            log.info("微信登陆失败___获取code异常___[{}]", wechatLogin.getCode());
            throw new BaseException("微信登陆失败");
        }
        //返回自定义的jsp页面 也可以返回结果集 让前台处理
        return Result.ok(carThirdUser);
    }

    @PostApi(value = "/queryMyInfo")
    @ApiOperation("我的资料")
    public Result queryMyInfo(){
        CarThirdUser carThirdUser = userUtil.getCurrentUser();
        if (carThirdUser == null || carThirdUser.getId() == null) {
            return Result.error("请登录");
        }
        return Result.ok(carThirdLoginService.queryMyInfo(carThirdUser.getId()));
    }

    @PostApi(value = "/updateMyInfo")
    @ApiOperation("我的资料修改")
    public Result updateMyInfo(@RequestBody @Valid CarThirdUserUpdateParam carThirdUserUpdateParam){
        return carThirdLoginService.updateMyInfo(carThirdUserUpdateParam, userUtil.getCurrentUser());
    }

    //小程序获取用户openid给前端
    @PostApi(value = "/loginByCode/{code}", auth = false)
    @ApiOperation(value = "code登录")
    public Result loginByCode(@PathVariable("code") String code) {
        //第三方登陆信息
        CarThirdUser carThirdUser ;
        Map<String, String> map ;
        //如果不为空
        if (StrUtil.isNotBlank(code)) {
            // 根据code获取token和openid
            map = carThirdLoginService.getWechatAndOpenid(code);
            map.remove("access_token");
            //获取 openid
            String openId = map.get("openId");
            //如果openID存在
            if (StrUtil.isNotBlank(openId)) {
                //生成token
                carThirdUser = carThirdLoginService.thirdPartyLogin(carThirdLoginService.getCarThirdUser(openId));
                map.put("token", carThirdUser.getToken());
            } else {
                log.info("微信登陆失败___获取openid异常___[{}]", openId);
                return Result.error("获取openId为空,登陆失败");
            }
        } else {
            log.info("微信登陆失败___获取code异常___[{}]", code);
            return Result.error("小程序code为空,登陆失败");
        }
        //返回自定义的jsp页面 也可以返回结果集 让前台处理
        return Result.ok(map);
    }
    //通过openid获取当前系统token
    @PostApi(value = "/getMyToken/{openid}", auth = false)
    @ApiOperation(value = "openid获取token")
    public Result getMyToken(@PathVariable("openid") String openid) {
        String token = (String) redisTemplate.boundHashOps(RedisKeyCode.LOGIN).get(openid);
        return Result.ok(token);
    }
}
